// import com.alibaba.druid.sql.ast.SQLStatement;
// import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
// import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
// import com.alibaba.druid.sql.ast.statement.SQLTableElement;
// import com.alibaba.druid.sql.ast.statement.SQLUniqueConstraint;
// import com.alibaba.druid.util.FnvHash;

#include "SchemaObject.h"
#include "../../utils/FnvHash.h"
#include "../../utils/instanceof.h"
#include "../ast/SQLStatement.h"
#include "../ast/statement/SQLCreateTableStatement.h"
#include "../ast/statement/SQLUniqueConstraint.h"

SchemaObject::SchemaObject(Schema_ptr schema, string_ptr name, SchemaObjectType_ptr type)
    : SchemaObject(schema, name, type, nullptr)
{
}

SchemaObject::SchemaObject(Schema_ptr schema, string_ptr name, SchemaObjectType_ptr type, SQLStatement_ptr statement)
{
  this->schema = schema;
  this->name = name;
  this->type = type;
  this->statement = statement;

  this->hashCode64 = FnvHash::hashCode64(name);
  rowCount = -1;
}

SQLObject_ptr SchemaObject::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<SchemaObject>(new SchemaObject(schema, name, type));
  std::shared_ptr<SchemaObject> x = std::dynamic_pointer_cast<SchemaObject>(clone_tmp);
  // SchemaObject_ptr x = SchemaObject_ptr(new SchemaObject(schema, name, type));

  if (statement != nullptr)
  {
    x->statement = std::dynamic_pointer_cast<SQLStatement>(statement->clone());
  }
  x->rowCount = rowCount;

  return x;
}

long SchemaObject::nameHashCode64()
{
  return hashCode64;
}

SQLStatement_ptr SchemaObject::getStatement()
{
  return statement;
}

SQLColumnDefinition_ptr SchemaObject::findColumn(string_ptr columName)
{
  long hash = FnvHash::hashCode64(columName);
  return findColumn(hash);
}

SQLColumnDefinition_ptr SchemaObject::findColumn(long columNameHash)
{
  if (statement == nullptr)
  {
    return nullptr;
  }

  if (instanceof <SQLStatement, SQLCreateTableStatement>(statement))
  {
    return (std::dynamic_pointer_cast<SQLCreateTableStatement>(statement))->findColumn(columNameHash);
  }

  return nullptr;
}

BOOL_ptr SchemaObject::matchIndex(string_ptr columnName)
{
  if (statement == nullptr)
  {
    return BOOL::FALSE;
  }

  if (instanceof <SQLStatement, SQLCreateTableStatement>(statement))
  {
    SQLTableElement_ptr index = (std::dynamic_pointer_cast<SQLCreateTableStatement>(statement))->findIndex(columnName);
    return (index != nullptr)?BOOL::TRUE:BOOL::FALSE;
  }

  return BOOL::FALSE;
}

BOOL_ptr SchemaObject::matchKey(string_ptr columnName)
{
  if (statement == nullptr)
  {
    return BOOL::FALSE;
  }

  if (instanceof <SQLStatement, SQLCreateTableStatement>(statement))
  {
    SQLTableElement_ptr index = (std::dynamic_pointer_cast<SQLCreateTableStatement>(statement))->findIndex(columnName);
    return (instanceof <SQLTableElement, SQLUniqueConstraint>(index))?BOOL::TRUE:BOOL::FALSE;
  }

  return BOOL::FALSE;
}

string_ptr SchemaObject::getName()
{
  return name;
}

SchemaObjectType_ptr SchemaObject::getType()
{
  return type;
}

long SchemaObject::getRowCount()
{
  return rowCount;
}

Schema_ptr SchemaObject::getSchema()
{
  return schema;
}
